<template>
    <div class="design-layout">
        <div class="mouse-tips" v-show="!!drawTips&&mouseInMap" :style="{left: mousePostition[0]+5+'px', top: mousePostition[1]+5+'px'}" v-html="drawTips"></div>
        <operationOptions v-model="leftSelected" @select="handleLeftSelect" :list="leftOptions" class="layout-left" />
        <operationOptions v-model="rightSelected" @select="handleRightSelect" :list="rightOptions" placement="left" class="layout-right" />
        <floatOptions v-model="geometryOptionShow" @change="handleGeometryTypeChange" type="icon" :list="geometryTypeList" :position="[40,190]" />
        <floatOptions v-model="contextmenuOptionsShow" @change="handleContextmenuSelect" type="text" :list="contextmenuOptions" :position="contextmenuOptionsPosition" />
        <floatOptions v-model="spiritListShow" type="spirit" :list="spiritList" :position="[40,275 ]" />
        <floatRightCard 
            :type="rightSelected" 
            :visible="mapSetShow" 
            :formData="mapInfoFormData" 
            @change="handleMapInfoChange"  
            @close="mapSetShow=false" 
            @sizeChange="handleSizeChange"
            @layer-status-change="hanleLayerStatusChange"
            />
        <div class="dl-canvas-box">
            <div 
                class="design-canvas" 
                @drop.prevent="handleContainerDrop"
                @dragover.prevent
                :style="{
                    width: designWidth+'px', 
                    height: designHeight+'px',
                    backgroundImage: showReferenceImage?`url(${mapBaseBg})`:'none',
                }" 
                ref="designCanvas">
            </div>
        </div>
    </div>
</template>
  
<script setup lang="ts">
import { ref, toRef, watch, computed, defineEmits, onMounted, reactive, onUnmounted } from 'vue';
import { useRoute } from 'vue-router';
import { useStore, mapState } from 'vuex';
//import mapDesignStore from './store';
import operationOptions from './operationOptions.vue';
import floatOptions from './floatOptions.vue';
import floatRightCard from './floatRightCard.vue';
import * as tools from './tools';
import type { Feature, OperationOptions } from '@/types/Design';
import { v4 as uuidv4 } from 'uuid';
import { focusNode } from 'element-plus/es/utils/index.js';
import * as geometric from 'geometric';
import { useEventListener } from '@/composable/common';
import * as util from  '@/utils';
import { ElAside, ElMessage } from 'element-plus';
import { functionsIn, minBy } from 'lodash';

console.log('%c ---地图系统初始化中---','color:green;')

interface Props {
	//width?: number;
	//height?: number;
    // svgString?:string;
    // name?:string;
    // description?:string;
    transformControlVisible?: string;
    lineControlVisible?: string;
}
const store = useStore();
const storeName = "mapDesign";
//store.registerModule(storeName, mapDesignStore);

//获取地图基础数据
const mapData = store.state[storeName].mapData;
const props = withDefaults(defineProps<Props>(),{
	//width: 2000,
    //height: 1068,
    transformControlVisible: 'hidden',
    lineControlVisible: 'hidden'
})
const emit = defineEmits<{
    'transform-change': [value: any],
    'sizeChange'
}>()

watch(()=>props.transformControlVisible,handleTransformControlVisible);

watch(()=>props.lineControlVisible,handleLineControlVisible);

const mapBaseBg = computed(()=> store.state[storeName].mapBaseImg);
console.log(mapBaseBg.value,'mapBaseBg----------com----')
// watch(mapBaseBg,val=>{
//     console.log(val,'mapBaseBgmapBaseBgmapBaseBg')
// })

const mouseTips = store.state[storeName].mouseTips;
const drawTips = ref('');
const mousePostition = ref([0,0]);
const designWidth = ref(mapData.width || 1920); //toRef(props.width);
const designHeight = ref(mapData.height || 1080); //toRef(props.height);
const designCanvas = ref(null);
const leftSelected = ref('map-move');
const mapSetShow = ref(false);
const showReferenceImage = ref(true);
const mapInfoFormData = ref<any>(null);

const leftOptions = ref<OperationOptions[]>(store.state[storeName].leftOptions);
const rightSelected = ref('');
const rightOptions = ref<OperationOptions[]>(store.state[storeName].rightOptions)
const geometryOptionShow = ref(false);
const geometryTypeList = ref(store.state[storeName].geometryOptions);
let geometryType = 'circle';

const contextmenuOptionsShow = ref(false);
const contextmenuOptions = ref(store.state[storeName].contextmenuOptions);
const contextmenuOptionsPosition = ref([0,0]);
let contextmenuOptionsPositionOrigin;
let operationType = '';

const spiritListShow = ref(false);
const spiritList = computed(()=>store.state[storeName].spiritList);

const drawingSvgElementIdName = "DRAWING-SVG-ELEMENT";
const shapeContainerIdName = "SHAPE-CONTAINER";
const routeContainerIdName = "ROUTE-CONTAINER";
const spiritContainerIdName = "SPIRIT-CONTAINER";
const controlSvgElementIdName = "CONTROL-SVG-ELEMENT";
const markContainerIdName = "MARK-CONTAINER";
const clipIdName = "CLIP-LINE";
const rectSelectIdName = "RECT-SELECT";
const deviceSpiritIdName = "DEVICE-SPIRIT";

const stairImg =  import.meta.env.VITE_FILE_HOST + '/images/20240112/1268838868806008832.png';

let selectedShapeEl;
let selectedShapeData;
let selectedShapeHolesData;
let contextSelectedEl;
let rectSelectedData;
const rectSelectedShapeMap = new Map();

//鼠标控制状态
let isMousedown: boolean = false;
let isDrawing: boolean = false; 
let currentDrawPolygonData: Array<number[]> = [];
let mouseDownPosition: [number,number] = [0,0];
let mouseMoveOffset: [number,number] = [0,0];
let mouseMovePosition: [number,number] = [0,0];
let mouseInMap = ref(false);
let mouseDownTarget;
let mouseDownTargetDragType;
let isShapeClip: boolean = false;
let isSpaceKeyMove: boolean = false;
let isAddHole: boolean = false;

const bounds = tools.createSvgElement('rect',{ 
    x: 0,
    y: 0,
    width: designWidth.value,
    height: designHeight.value,
    fill: 'white' 
})

const polygonStyles = {
    "stroke": "rgba(158,189,254)",      
    "stroke-width": 1,
    "fill": "rgba(158,189,254,0.5)"
}

let draggableLayout;
let svgDocument;
const isDrawPolygon = computed(() => {
  return leftSelected.value == 'draw-polygon'
})
const isDrawGeometry = computed(() => {
  return leftSelected.value == 'draw-geometry'
})
const isPointer = computed(() => {
  return leftSelected.value == 'pointer'
})
const isRectSelect = computed(() => {
  return leftSelected.value == 'rect-select'
})
const isNavigationRoute = computed(() => {
  return leftSelected.value == 'draw-line'
})
const isDrawDevice = computed(() => {
  return leftSelected.value == 'draw-device'
})

watch(leftSelected,val=>{
    clearRectSelect();
    if(val == 'map-move'){
        draggableLayout.disabled = false;
    }else{
        draggableLayout.disabled = true;
    }
    svgDocument.style.pointerEvents = 'none';
    if(val == 'pointer' || val == 'draw-line'){
        svgDocument.style.pointerEvents = 'auto';
    }
})
defineExpose({
    setSvgDocument,
    setDesignScale,
    getSvgString,
    handleShapeAlign
})

function getSvgString(){
    clearRectSelect();
    const svg = svgDocument.cloneNode(true);
    svg.removeAttribute('style');
    //清理选择工具
    const cse = svg.getElementById(controlSvgElementIdName);
    if(cse)cse.remove();
    //清除显示状态属性
    svg.childNodes.forEach(el=>el.removeAttribute('visibility'));
    const div = document.createElement('div');
    div.appendChild(svg);
    //清理下hover状态

    return div.innerHTML
}

function setDesignScale(value){
    setLayoutScaleWidthCenter(value);
    // draggableLayout.scale = value;
    // draggableLayout.transformCanvas();
}

//历史存储
function hanldleHistoryStorage(){
    console.log('记录一次变化')
    setTimeout(() => {
        // const svg = svgDocument.cloneNode(true);
        // const cse = svg.getElementById(controlSvgElementIdName);
        // if(cse)cse.remove();
        // //清理下hover状态
        store.dispatch(storeName+'/addMapDataHistory',getSvgString());
       // console.log(store.state[storeName].mapDataHistoryStorage.length,'---当前的历史记录次数---')
    }, 200);
    
}

//标注层渲染
function markLayerRender(){
    const markContainer = getSvgElementById(markContainerIdName);
    const shapes = svgDocument.querySelectorAll('[shape-type]');
    shapes.forEach(el=>{
        const title = el.getAttribute('title');
        if(!el.hasAttribute('is-hole') && title){
            const id = el.id;
            const position = geometric.polygonCentroid(getShapeOutlineAll(getBorderPointCollect(el))); 
            const textNodeId = "text-"+id
            let textNode = markContainer.querySelector("#"+textNodeId);
            if(!textNode){
                textNode = tools.createSvgElement('text');
                markContainer.appendChild(textNode);
            }
            textNode.textContent = title;
            tools.setElementAttribute(textNode,{
                x: position[0],
                y: position[1],
                id: textNodeId,
                'font-size': '12px',
                'text-anchor': 'middle',
                'dominant-baseline': "middle",
                'stroke': '#fff',
                'stroke-width': 0.2

            });
        }
    })
    //清除多余的文字标注
    markContainer.childNodes.forEach(tl=>{
        //console.log(tl.id.split('-')[1],'6789------')
        if(!svgDocument.querySelector('#'+tl.id.replace(/^text-/,''))){
            tl.remove();
        }
    })
}

//绘制设备区域
function handleSetDeviceSpirit(){
    const deviceSpiritContainer = getSvgElementById(deviceSpiritIdName);
    const shapes = svgDocument.querySelectorAll('[shape-type]');
    shapes.forEach(el=>{
        if(el.getAttribute('shape-type') == 'rect' && el.hasAttribute('is-stair')){
            const pointCollect = getBorderPointCollect(el);
            const xLine = [pointCollect[0][1],pointCollect[1][1]];
            const yLine = [pointCollect[1][1],pointCollect[2][1]];
            const rectWidth = geometric.lineLength(xLine);
            const rectHeight = geometric.lineLength(yLine);
            const rectAngle = geometric.lineAngle(xLine);
            const position = geometric.polygonCentroid(getShapeOutlineAll(pointCollect)); 

            const deviceId = "device-"+el.id
            let deviceNode = deviceSpiritContainer.querySelector("#"+deviceId);
            if(!deviceNode){
                deviceNode = tools.createSvgElement('image');
                deviceSpiritContainer.appendChild(deviceNode);
            }
            const x = pointCollect[0][1][0];
            const y = pointCollect[0][1][1];
            //绘制楼梯标示图
            tools.setElementAttribute(deviceNode,{
                'id': deviceId,
                href: stairImg, 
                width: rectWidth, 
                height: rectHeight, 
                x,
                y,
               // transform: `translate(-${rectWidth/2}, -${rectHeight/2}) rotate(45deg)`,
               transform: `rotate(${rectAngle})`,
                "transform-origin": `${x} ${y}`
            })
        }
    })
    
    //清除多余的设备图片标注
    deviceSpiritContainer.childNodes.forEach(tl=>{
        //console.log(tl.id.split('-')[1],'6789------')
        const matchEl = svgDocument.querySelector('#'+tl.id.replace(/^device-/,''));
        if(!matchEl || !matchEl.hasAttribute('is-stair')){
            tl.remove();
        }
    })
}

async function setSvgDocument(type){
    const svgString = await store.dispatch(storeName+'/getHistoryMapData',type);
    if(svgString){
        renderSvgString(svgString);
    }
}

function renderSvgString(svgString){
    console.log(svgString,'svgStringsvgStringsvgStringsvgString--')
    designCanvas.value.innerHTML = svgString;
    svgDocument = designCanvas.value.childNodes[0];
    svgDocument.style.pointerEvents = leftSelected.value == 'pointer'?'auto':'none';
    clearControlContainer();
    //修正样式
    const shapes = svgDocument.querySelectorAll('[shape-type]');
    const navPoints = svgDocument.querySelectorAll('[c-type=nav-point]');
    const navLines = svgDocument.querySelectorAll('[c-type=nav-line]');
    shapes.forEach(item=>{ tools.setElementAttribute(item,{ "stroke": polygonStyles["stroke"], "stroke-width": polygonStyles["stroke-width"]}) })
    navPoints.forEach(item=>{ tools.setElementAttribute(item,{"stroke": "#67C23A"}) })
    navLines.forEach(item=>{ tools.setElementAttribute(item,{"stroke": "#67C23A"}) })
    //重置preNavPoint
    if(!preNavPoint)preNavPoint = getSvgElementById(routeContainerIdName).querySelector('circle:last-of-type');
    //修正图层状态---ing
    const layers = store.state[storeName].layers;
    svgDocument.childNodes.forEach(el=>{
        const layerItem = layers.find(l=>l.containerIds?.includes(el.id));
        if(layerItem)tools.setElementAttribute(el,{ visibility: layerItem.visible?'visible':'hidden'});
    })
}

function hanleLayerStatusChange(item){
    //console.log(item,'hanleLayerStatusChange')
    if(item.value==1){
        showReferenceImage.value = item.visible;
    }else{
        item.containerIds.split(',').forEach(id => {
            tools.setElementAttribute(getSvgElementById(id),{ visibility: item.visible?'visible':'hidden'});
        });
    }
}

function isSelectedMaskShape(shape){
    return shape.getAttribute('mask-id') && selectedShapeHolesData
}

function handleContextmenuSelect(data){
    //右击选项选中
    const el = contextSelectedEl;
    //console.log(el,'contextSelectedElcontextSelectedEl')
    if(el.getAttribute('c-type') == 'outline-item'){
        const indexLinkArray = el.getAttribute('index-link').split(',').map(v=>parseInt(v));
        const index1 = indexLinkArray[0];
        const index2 = indexLinkArray[1];
        const start = selectedShapeData[index1];
        const end = selectedShapeData[index2];
        console.log(start,end,'线段--弧线------')
        if(data.value == 1){
            //线段转弧线
            const startPoint = start[start.length-1];
            const endPoint =  end[1];
            const lineAngle = geometric.lineAngle([startPoint,endPoint]);
            //console.log(lineAngle,'lineAngle')
            const pointTranslateAngle = lineAngle + 90;
            let p1 = geometric.pointTranslate(startPoint,pointTranslateAngle,30);
            let p2 = geometric.pointTranslate(endPoint,pointTranslateAngle,30);
            const lip = geometric.lineInterpolate([p1,p2]);
            if(geometric.lineIntersectsPolygon([lip(-1),lip(2)], getShapeOutline())){
                p1 = geometric.pointTranslate(startPoint,pointTranslateAngle,-30);
                p2 = geometric.pointTranslate(endPoint,pointTranslateAngle,-30);
            }
            const curvePoints = [ "C", p1, p2, endPoint ];
            //geometric.lineIntersectsPolygon(line, polygon);
            if(index2 == 0){
                //结束点为起始点则添加一个新点
                selectedShapeData.push(curvePoints);
            }else{
                selectedShapeData[index2] = curvePoints;
            }

        }else if(data.value == 2){
            //弧线转线段
            selectedShapeData[index2] = [ "L", end[end.length-1] ];
        }else if(data.value == 3){
            //添加轮廓点
            const startPoint = start[start.length-1];
            const endPoint =  end[end.length-1];
            const current = transformCoordinate(...contextmenuOptionsPositionOrigin);
            const interpolate = geometric.lineInterpolate([startPoint,endPoint],true);
            const countResult = interpolate(geometric.lineLength([startPoint,current])/geometric.lineLength([startPoint,endPoint]))
            console.log(countResult,'geometric.lineLength--')
            if(index2>0){
                selectedShapeData.splice(index2,0,['L',countResult]);
            }else{
                selectedShapeData.push(['L',countResult]); //如果线段是与开始点连接的，则在结尾增加一个点
            }
            
        }
        resetShape(selectedShapeEl,selectedShapeData);
        clearControlContainer();
        setShapeControlBounding(selectedShapeEl);
    }
    if(selectedShapeEl){
        if(data.value == 5){
            //删除
            if(isSelectedMaskShape(selectedShapeEl)){
                const { mask, holes } = selectedShapeHolesData;
                mask.remove();
                for( let shape of holes.keys()){
                    shape.remove();
                }
            }
            if(selectedShapeEl.hasAttribute('is-hole')){
                getSvgElementById(shapeContainerIdName).querySelector('#hole-'+selectedShapeEl.id).remove();
            }
            selectedShapeEl.remove();
            clearSelectStatus();
            markLayerRender(); //标注渲染
            handleSetDeviceSpirit(); //设备图示渲染
        }
        if(data.value == 6){
            //复制
            if(isSelectedMaskShape(selectedShapeEl)){
                handleMaskShapeCopy();
            }else{
                createShapeFromCalculatedData(getShapeTranslateResult(45,30));
            }
            
        }
        if(data.value == 7){
            //分割
            isShapeClip = true;
            drawTips.value = mouseTips['shape-clip'];
            showNecessaryControlEl(['c-outline-paths']);
            console.log('可以绘制分割线');
        }
        if(data.value == 4){
            if(selectedShapeData.length<4){
                ElMessage.error('轮廓至少要三个点');
                return
            }
            //删除轮廓点
            const index = parseInt(el.getAttribute('indexs').split('_')[0]);
            if(index < selectedShapeData.length - 1){//非最后一个点
                if(selectedShapeData[index+1][0] == 'C'){
                    selectedShapeData[index+1] = ['L',selectedShapeData[index+1][3]]
                }
                if(index==0){
                    //第一个点  
                    selectedShapeData[index+1][0] = 'M';
                }
            }
            
            selectedShapeData.splice(index,1);
            console.log(selectedShapeData,'selectedShapeData------删除点')
            resetShape(selectedShapeEl,selectedShapeData,false);
            clearControlContainer();
            setShapeControlBounding(selectedShapeEl);
        }
        if(data.value == 8){
            //添加镂空
            isAddHole = true;
            drawTips.value = mouseTips['add-hole'] || '';
            showNecessaryControlEl(['c-outline-paths']);

        }
        if(data.value == 10){
          //置于顶层
            selectedShapeEl.remove();
            getSvgElementById(shapeContainerIdName).appendChild(selectedShapeEl);
            clearControlContainer();
        }
        if(data.value == 11){
            //置于底层
            selectedShapeEl.remove();
            getSvgElementById(shapeContainerIdName).prepend(selectedShapeEl);
            clearControlContainer();
        }
    }
    if(data.value == 9){
        const lines = getNavLinesByPoint(el.id);
        lines.asStartLines.concat(lines.asEndLines).forEach(l=>{l.remove()});
        el.remove();
    }
    if(data.value == 12){
        el.remove();
    }
    hanldleHistoryStorage();
}

function handleGeometryTypeChange(data){
    leftOptions.value[4].icon = data.icon;
    geometryType = data.value;
}

function handleSizeChange(data){
    console.log(data,'ewewe')
    designWidth.value = data.width;
    designHeight.value = data.height;
    tools.setElementAttribute(svgDocument, {
        'width': data.width,
        'height': data.height
    })
    hanldleHistoryStorage();
    emit('sizeChange');
}

function handleRightSelect(data){
    const val = data.value;
    mapInfoFormData.value = null;
    if(val == 'element-attribute'&&selectedShapeEl&&!selectedShapeEl.hasAttribute('is-hole')){
        mapInfoFormData.value = {
            title: selectedShapeEl.getAttribute('title')||'',
            color: selectedShapeEl.getAttribute('fill'),
            thickness: parseFloat(selectedShapeEl.getAttribute('thickness')||0),
            isBottom: selectedShapeEl.hasAttribute('is-bottom'),
            isStair: selectedShapeEl.hasAttribute('is-stair'),
            shapeType: selectedShapeEl.getAttribute('shape-type')
        }
    }
    mapSetShow.value = true;
}

function handleMapInfoChange(value,type){
    console.log(value,type);
    if(type == 'element-attribute'&&selectedShapeEl&&!selectedShapeEl.hasAttribute('is-hole')){
        const attr = {
            title: value.title,
            fill: value.color,
            thickness: value.thickness
        }
        tools.removeElementAttribute(selectedShapeEl,['is-bottom','is-stair']);
        if(value.isBottom){
            attr['is-bottom'] = true;
        }
        if(value.isStair){
            attr['is-stair'] = true;
        }
        tools.setElementAttribute(selectedShapeEl,attr);
        markLayerRender(); //标注渲染
        handleSetDeviceSpirit(); //设备图示渲染
        hanldleHistoryStorage(); 
        
    }
    // else if(type == 'map-set'){

    // }
}

function handleLeftSelect(data){
    const val = data.value;
    geometryOptionShow.value = false;
    spiritListShow.value = false;
    if(val == 'draw-geometry'){
        geometryOptionShow.value = true;
    }
    if(val == 'put-spirit'){
        spiritListShow.value = true;
    }
    if(val != 'pointer'){
        clearSelectStatus();
    }
    drawTips.value = mouseTips[val] || '';
    
}

function initSvgMap(){
    const container:any = designCanvas.value;
    svgDocument = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
    tools.setElementAttribute(svgDocument, {
        "xmlns": "http://www.w3.org/2000/svg",
        "xmlns:xlink": "http://www.w3.org/1999/xlink",
        "version": "1.1",
        "width": designWidth.value,
        "height": designHeight.value
    })
    svgDocument.style.pointerEvents = 'none';
    const shapeContainer = tools.createSvgElement('g',{id: shapeContainerIdName});
    const routeContainer = tools.createSvgElement('g',{id: routeContainerIdName});
    const spiritContainer = tools.createSvgElement('g',{id: spiritContainerIdName});
    const markContainer = tools.createSvgElement('g',{id: markContainerIdName, 'pointer-events': 'none'});//标注层
    const deviceSpiritContainer = tools.createSvgElement('g',{id: deviceSpiritIdName, 'pointer-events': 'none'});
    svgDocument.append(shapeContainer,routeContainer,spiritContainer,markContainer,deviceSpiritContainer);
    // svgDocument.appendChild(routeContainer);
    // svgDocument.appendChild(spiritContainer);
    container.appendChild(svgDocument);
    //svgDocument.addEventListener('click',handleSvgDocumentClick);
    bindDrawEvent();
    if(mapData.svg)renderSvgString(mapData.svg);
    if(!svgDocument.querySelector('#'+shapeContainerIdName)){
        svgDocument.append(shapeContainer);
    }
    if(!svgDocument.querySelector('#'+routeContainerIdName)){
        svgDocument.append(routeContainer);
    }
    if(!svgDocument.querySelector('#'+spiritContainerIdName)){
        svgDocument.append(spiritContainer);
    }
    if(!svgDocument.querySelector('#'+markContainerIdName)){
        svgDocument.append(markContainer);
    }
    if(!svgDocument.querySelector('#'+deviceSpiritIdName)){
        svgDocument.append(deviceSpiritContainer);
    }
    //记录一次
    hanldleHistoryStorage();
}

function clearControlContainer(){
    getControlContainer()?.remove();
}
function clearSelectStatus(){
    selectedShapeEl = null;
    selectedShapeData = null;
    selectedShapeHolesData = null;
    contextSelectedEl = null;
    clearAddHoleStatus();
    clearControlContainer();
}

function clearAddHoleStatus(){
    isAddHole = false;
    drawTips.value = '';
}

function isShapeElement(el){
    return el.getAttribute('shape-type') && el.nodeName == 'path'
}

function handleSvgDocumentClick(e){
    console.log(e,'handleSvgDocumentClick')
    e.preventDefault();
    if(isShapeElement(e.target)){
        if( getControlContainer() && e.target.id == selectedShapeEl.id){
            //点击已选择的形状不做处理
            return 
        }
        if(isAddHole){
            //添加镂空
           handleShapeAddHole(e.target);

        }else{
            //重新选择新的
            clearSelectStatus();
            selectedShapeEl = e.target;
            setShapeControlBounding(selectedShapeEl);
            //属性信息框
            rightSelected.value = 'element-attribute';
            handleRightSelect({value: rightSelected.value});
        }
    }else{
        if(mouseDownTarget.nodeName == 'svg'){
            mouseDownTarget = null;
            //空白处取消选择状态
            clearSelectStatus();
        }
    }
}

function handleMaskShapeCopy(){
    const shapeContainer = getSvgElementById(shapeContainerIdName);
    const { holes } = selectedShapeHolesData;
    const newShape = selectedShapeEl.cloneNode(true);
    const id = 'shape_'+uuidv4();
    const maskId = 'mask-'+id;
    const d = getDfromShapeData(getShapeTranslateResult(45,30));
    tools.setElementAttribute(newShape,{ 'mask-id': maskId, mask: `url(#${maskId})`, id, d });
    shapeContainer.appendChild(newShape);
     

    const mask = tools.createSvgElement('mask',{ id: maskId });
    mask.appendChild(bounds.cloneNode(true));
    shapeContainer.prepend(mask);
    for (let holeShapeEl of holes.keys()) {
        const newHoleShapeEl = holeShapeEl.cloneNode(true);
        const newHoleShapeD = getDfromShapeData(getShapeTranslateResult(45,30,holes.get(holeShapeEl)));
        tools.setElementAttribute(newHoleShapeEl,{ id: 'shape_'+uuidv4(), d: newHoleShapeD });
        shapeContainer.appendChild(newHoleShapeEl);
        mask.appendChild(createHoleInMask(newHoleShapeEl));

    }

}

function handleShapeAddHole(holeShapeEl){
    //镂空逻辑
    if(holeShapeEl.getAttribute('mask-id')){
        ElMessage.error('不能选择已是镂空的形状！');
        clearSelectStatus();
        return
    }
    if(holeShapeEl.hasAttribute('is-hole')){
        return
    }
    //判断两个形状是否相交
    const polygonA = getShapeOutline(changeCurveShapeToPolygon(selectedShapeData));
    const polygonB = getShapeOutline(changeCurveShapeToPolygon(getBorderPointCollect(holeShapeEl)));
    if(!geometric.polygonInPolygon(polygonB,polygonA)){
        ElMessage.error('添加镂空失败，选择的形状必须要在当前图形内部');
        clearSelectStatus();
        return
    }
    const maskId = 'mask-'+selectedShapeEl.id;
    let mask = getSvgElementById(shapeContainerIdName).querySelector('#'+maskId);
    if(!mask){
        mask = tools.createSvgElement('mask',{ id: maskId });
        mask.appendChild(bounds.cloneNode(true));
        tools.setElementAttribute(selectedShapeEl,{ 'mask-id': maskId, mask: `url(#${mask.id})` });
        getSvgElementById(shapeContainerIdName).prepend(mask);
    }
    const hole = createHoleInMask(holeShapeEl);//holeShapeEl.cloneNode(true);
    //tools.setElementAttribute(hole,{ id: 'hole-'+holeShapeEl.id, fill: 'black', 'stroke-width': 0 });
    mask.appendChild(hole);
    tools.setElementAttribute(holeShapeEl,{fill: 'rgba(255,255,255,0)','is-hole': true});
    clearSelectStatus();
}

function createHoleInMask(holeShapeEl){
    const hole = holeShapeEl.cloneNode(true);
    hole.removeAttribute('is-hole')
    tools.setElementAttribute(hole,{ id: 'hole-'+holeShapeEl.id, fill: 'black', 'stroke-width': 0 });
    return hole
}

function handleSvgDocumentContextmenu(e){
    contextSelectedEl = e.target;
    if(isShapeElement(e.target)&&selectedShapeEl&&e.target.id == selectedShapeEl.id){
        if(e.target.hasAttribute('is-hole')){
            showContextmenuOptions(e,[5]);
        }else if(e.target.getAttribute('mask-id')){
            showContextmenuOptions(e,[5,6,8,10,11]);
        }else{
            showContextmenuOptions(e,[5,6,7,8,10,11]);
        }
        //contextSelectedEl = e.target;
    }
    const cType = e.target.getAttribute('c-type');
    if(cType == 'point-line'){
        showContextmenuOptions(e,[4])
    }
    if(cType == 'outline-item'){
        if(isRectShape())return //矩形不允许修改
        const lineType = e.target.getAttribute('line-type');
        if(lineType == 'line'){
            showContextmenuOptions(e,[1,3])
        }else{
            showContextmenuOptions(e,[2])
        }
    }
    if(cType == 'nav-point'){
        showContextmenuOptions(e,[9]);
    }
    if(cType == 'spirit'){
        showContextmenuOptions(e,[12]);
    }
}

function getShapeMaskData(maskId){
    let mask = getSvgElementById(shapeContainerIdName).querySelector('#'+maskId);
    const holes = new Map();
    mask.querySelectorAll('path').forEach(item=>{
        const id = item.id.replace(/^hole-/,'');
        const holeShapeEl = getSvgElementById(shapeContainerIdName).querySelector('#'+id);
        holes.set(holeShapeEl,getBorderPointCollect(holeShapeEl))
    });
    return { mask, holes }
}

function setShapeControlBounding(shape){
    const borderPointCollect = getBorderPointCollect(shape);
    const mapScale = store.state[storeName].mapScale;
    selectedShapeData = borderPointCollect; //更新数据
    let circles = [];
    let lines = [];
    const cTypes = [ 'point-line', 'point-curve' ];
    //console.log(shape.getAttribute('shape-type'),'borderPointCollect')
    for(let [index,item] of borderPointCollect.entries()){
        if(['M','L'].includes(item[0])){
            const p = tools.createControlCircle(item[1]);
            tools.setElementAttribute(p, { indexs: index+'_1', 'c-type': cTypes[0] });
            circles.push(p);
        }else if(item[0]=='C'){
            //曲线控制点
            const pos0 = borderPointCollect[index-1][borderPointCollect[index-1].length-1];
            const pos0Index = (index-1)+'_'+(borderPointCollect[index-1].length-1);

            const p1 = tools.createControlCircle(item[1],2);
            const p1Index = index+'_1';
            tools.setElementAttribute(p1, { indexs: p1Index, 'c-type': cTypes[1] });

            const p2 = tools.createControlCircle(item[2],2);
            const p2Index = index+'_2';
            tools.setElementAttribute(p2, { indexs: p2Index, 'c-type': cTypes[1] });

            const end = tools.createControlCircle(item[3]);
            const endIndex = index+'_3';
            tools.setElementAttribute(end, { indexs: endIndex, 'c-type': cTypes[0] });

            const line1 = tools.createCurveControlLine(pos0,item[1]);
            tools.setElementAttribute(line1, { 'c-type': 'line-curve', 'index-link': pos0Index+','+p1Index});
            const line2 = tools.createCurveControlLine(item[2],item[3]);
            tools.setElementAttribute(line2, {  'c-type': 'line-curve', 'index-link': p2Index+','+endIndex});
            circles = circles.concat(p1,p2,end);
            lines = lines.concat(line1,line2);
        }
    }

    //增加镂空存储
    const maskId = shape.getAttribute("mask-id");
    if(maskId){
        selectedShapeHolesData = getShapeMaskData(maskId);
    }
    const shapeCenter = getSelectedShapeCenter();
    //创建平移标识
    const shapeTranslateCircle = tools.createControlCircle(shapeCenter,3);
    tools.setElementAttribute(shapeTranslateCircle,{ 'id': 'c-translate', 'c-type': 'c-translate'});

    const iconSizeStyle = {
        width: 24/mapScale,
        height: 24/mapScale,
        transform: `translate(-${12/mapScale}, -${12/mapScale})`
    }
    //创建旋转标识
    const shapeRotateIconPosition = geometric.pointTranslate(shapeCenter,0,60);
    const shapeRotateIcon = tools.createSvgElement('image',{ 'id': 'c-rotate', 'c-type': 'c-rotate', href: new URL(`/src/assets/images/rotate.png`, import.meta.url).href, x: shapeRotateIconPosition[0], y: shapeRotateIconPosition[1], ...iconSizeStyle })
    const translateRotateControlLine = tools.createCurveControlLine(shapeCenter,shapeRotateIconPosition);
    tools.setElementAttribute(translateRotateControlLine,{ 'id': 'line-transform-rotate', "stroke-width": 2/mapScale, 'c-type': 'line-transform-rotate', 'stroke-dasharray': '5 5' });
     
    //创建缩放标识
    const shapeScaleIconPosition = geometric.pointTranslate(shapeCenter,135,getScaleLineLength(shapeCenter));
    const shapeScaleIcon = tools.createSvgElement('image',{ 'id': 'c-scale', 'c-type': 'c-scale', href: new URL(`/src/assets/images/scale.png`, import.meta.url).href, x: shapeScaleIconPosition[0], y: shapeScaleIconPosition[1], ...iconSizeStyle })
    const translateScaleControlLine = tools.createCurveControlLine(shapeCenter,shapeScaleIconPosition);
    tools.setElementAttribute(translateScaleControlLine,{ 'id': 'line-transform-scale', "stroke-width": 2/mapScale, 'c-type': 'line-transform-scale', 'stroke-dasharray': '5 5' });

    createControlSvgContainer([translateScaleControlLine,shapeScaleIcon,translateRotateControlLine,shapeTranslateCircle,shapeRotateIcon,...lines,...circles]);
    createOutlinePath(borderPointCollect);
    handleTransformControlVisible(props.transformControlVisible);
    handleLineControlVisible(props.lineControlVisible);
}

function isRectShape(){
    return selectedShapeEl?.getAttribute('shape-type') == 'rect'
}

function handleTransformControlVisible(type){
    let ids = [ 'c-translate', 'line-transform-rotate', 'c-rotate', 'line-transform-scale', 'c-scale' ];
    setControlVisibleByIds(ids,type);
    //根据shapeType 强制控件隐藏
    // if(isRectShape()){
    //     //矩形只保留平移
    //     setControlVisibleByIds(['line-transform-rotate', 'c-rotate', 'line-transform-scale', 'c-scale' ],'hidden');
    // }
}

function setControlVisibleByIds(ids,type){
    const container = getControlContainer();
    if(!container)return
    for(let id of ids){
        const el = container.querySelector('#'+id);
        tools.setElementAttribute(el,{ visibility: type });
    }
}

function handleLineControlVisible(type){
    setLineControlVisible(type);
    // if(isRectShape()){
    //     //矩形只保留平移
    //     setLineControlVisible('hidden');
    // }
}

function setLineControlVisible(type){
    const container = getControlContainer();
    if(!container)return
    const g = container.querySelector('#'+'c-outline-paths');
    g.childNodes.forEach(el => {
        if(el.getAttribute('c-type') == 'outline-translate'){
            tools.setElementAttribute(el,{ visibility: type })
        }
    });
}

function getScaleLineLength(shapeCenter){
    return  Math.max(...getShapeOutlineAll().map(v=>geometric.lineLength([v,shapeCenter]))) * 0.5;
}

function getShapeTranslateResult(angle:number,distance:number,shapeData?:any){
    const pathData = (shapeData || selectedShapeData);
    return pathData.map(item=>{
        return item.map((v,i)=>{
            return i>0?geometric.pointTranslate(v,angle,distance):v;
        })
    })
}

function getShapeRotateResult(angle,center,shapeData){
    const pathData = (shapeData || selectedShapeData);
    const { polygon, recordIndexs } = getShapePolygonDataGroup(pathData);
    //单独取出顶点组合成数组，按照索引记录原先的分组规则
    // const recordIndexs = [];
    // let polygon = [];
    // let index = 0;
    // pathData.forEach((item)=>{
    //     const pointsArray = item.slice(1);
    //     recordIndexs.push(pointsArray.map(()=>index++));
    //     polygon = polygon.concat(pointsArray);
    // })
   
    const rotateResult = geometric.polygonRotate(polygon,angle,center);
    return pathData.map((item,i)=>{
        return [ item[0], ...recordIndexs[i].map(v=>rotateResult[v]) ]
    })
}

function getShapeScaleResult(scaleFactor,center,shapeData?:any){
    const pathData = (shapeData || selectedShapeData);
    const { polygon, recordIndexs } = getShapePolygonDataGroup(pathData);
    const scaleResult = geometric.polygonScale(polygon,scaleFactor,center);
    return pathData.map((item,i)=>{
        return [ item[0], ...recordIndexs[i].map(v=>scaleResult[v]) ]
    })
}

function getShapePolygonDataGroup(pathData){
    const recordIndexs = [];
    let polygon = [];
    let index = 0;
    pathData.forEach((item)=>{
        const pointsArray = item.slice(1);
        recordIndexs.push(pointsArray.map(()=>index++));
        polygon = polygon.concat(pointsArray);
    })
    return {
        polygon,
        recordIndexs
    }
}

function getSelectedShapeCenter(){
    //找出中心点
    return geometric.polygonCentroid(getShapeOutlineAll()); 
}

function getShapeOutlineAll(data?:any){
    return (data || selectedShapeData).reduce((collect,item)=>{
        return collect.concat(item.slice(1));
    },[])
}

function getShapeOutline(data){
    const polygon = (data || selectedShapeData).reduce((collect,item)=>{
        return collect.concat(item.slice(item.length-1));
    },[])
    //console.log(polygon,'polygon---')
    polygon.push(polygon[0])
    return geometric.polygonHull(polygon);
}

function updateTransformMark(params?:any = {}){
    const { center, angle, scaleLineLength } = params;
    //参数非必填，传参为触发事件时更新，无参数表示按照形状数据更新
    const controlContainer = getControlContainer();
    const shapeCenter = center || getSelectedShapeCenter();

    //平移标识更新
    const shapeTranslateCircle = controlContainer.querySelector('#c-translate');
    tools.setElementAttribute(shapeTranslateCircle,{ cx: shapeCenter[0], cy: shapeCenter[1] });

    //旋转标识更新
    const shapeRotateIconPosition = geometric.pointTranslate(shapeCenter,angle || 0,60);
    const shapeRotateIcon = controlContainer.querySelector('#c-rotate');
    tools.setElementAttribute(shapeRotateIcon,{ 'x': shapeRotateIconPosition[0], 'y': shapeRotateIconPosition[1] });
    const translateRotateControlLine = controlContainer.querySelector('#line-transform-rotate');
    tools.setElementAttribute(translateRotateControlLine,{ 
        "x1": shapeCenter[0],
        "y1": shapeCenter[1],
        "x2": shapeRotateIconPosition[0],
        "y2": shapeRotateIconPosition[1]
    }); 

    //缩放标识更新
    const shapeScaleIconPosition = geometric.pointTranslate(shapeCenter,135,scaleLineLength || getScaleLineLength(shapeCenter));
    const shapeScaleIcon =  controlContainer.querySelector('#c-scale');
    tools.setElementAttribute(shapeScaleIcon,{ 'x': shapeScaleIconPosition[0], 'y': shapeScaleIconPosition[1] });
    const translateScaleControlLine = controlContainer.querySelector('#line-transform-scale');
    tools.setElementAttribute(translateScaleControlLine,{ 
        "x1": shapeCenter[0],
        "y1": shapeCenter[1],
        "x2": shapeScaleIconPosition[0],
        "y2": shapeScaleIconPosition[1]
    }); 
}

function updateSplitPath(shapeData?:any){
    const pathData = (shapeData || selectedShapeData);
    const g = getControlContainer().querySelector('#c-outline-paths');
    g.childNodes.forEach((el,index)=>{
        const [index1,index2] = el.getAttribute('index-link').split(',').map(v=>parseInt(v));
        const item1 = pathData[index1];
        const item2 = pathData[index2];
        if(el.getAttribute('c-type')=='outline-item'){
            tools.setElementAttribute(el,{
                "d": getPathDFromLinkData(item1,item2)
            })
        }else{
            tools.setElementAttribute(el,{
                ...getOutlinePathMiddleControlLineData(item1,item2)
            })
        }
        
    })
}


function createOutlinePath(data){
    const pathsG = tools.createSvgElement('g',{ id: 'c-outline-paths' });
    const pathItems: any = [];
    const lineCenters: any = [];
    for(let [index,item] of data.entries()){
        if(index>0){
            const attrs = {'index-link': `${index-1},${index}`};
            const pathItem = createOutlinePathItem(data[index-1],item);
            tools.setElementAttribute(pathItem,attrs);
            pathItems.push(pathItem);
            const lineCenter = createOutlinePathMiddleControl(data[index-1],item);
            if(lineCenter){
                //pathsG.appendChild(lineCenter);
                tools.setElementAttribute(lineCenter,attrs)
                lineCenters.push(lineCenter)
            }
           // pathsG.appendChild(pathItem);
        }
    }
    const pathEnd = createOutlinePathItem(data[data.length-1],data[0]);
    //tools.setElementAttribute(pathEnd,{'index-link': `${data.length-1},${0}`})
    const pathEndLinCenter = createOutlinePathMiddleControl(data[data.length-1],data[0]);
    tools.setElementAttribute([pathEnd,pathEndLinCenter],{'index-link': `${data.length-1},${0}`})
    pathItems.push(pathEnd);
    lineCenters.push(pathEndLinCenter);


    pathsG.append(...pathItems,...lineCenters);

    // pathsG.childNodes.forEach(element => {
    //     element.addEventListener('contextmenu',e=>{ 
    //         contextSelectedEl = element;
    //         const lineType = element.getAttribute('line-type');
    //         if(lineType == 'line'){
    //             showContextmenuOptions(e,[1,3])
    //         }else{
    //             showContextmenuOptions(e,[2])
    //         }
    //     })
    //     // element.addEventListener('mouseover',e=>{ 
    //     //     if(element.getAttribute('c-type')=='outline-item')tools.setElementAttribute(element, { stroke: '#05286d' }) 
    //     // });
    //     // element.addEventListener('mouseout',e=>{ 
    //     //     if(element.getAttribute('c-type')=='outline-item')tools.setElementAttribute(element, { stroke: '#77a3fd' }) 
    //     // })
    // });
    getControlContainer().prepend(pathsG);
}

function showContextmenuOptions(e,values){
    contextmenuOptionsShow.value = true;
    contextmenuOptionsPositionOrigin = [e.clientX,e.clientY];
    contextmenuOptionsPosition.value = getContextmenuOptionsPosition(e);
    setContextmenuOptionsByValues(values);
}

function setContextmenuOptionsByValues(values){
    contextmenuOptions.value = store.state[storeName].contextmenuOptions.filter(v=>values.includes(v.value));
}

function getContextmenuOptionsPosition(e){
    return  Object.values(windowToMap(e.clientX,e.clientY)).map(v=>v+5)
}

function createOutlinePathMiddleControl(item1,item2){
    const mapScale = store.state[storeName].mapScale;
    if(item2[0]!='C'){
        const el = tools.createSvgElement('line',{
            ...getOutlinePathMiddleControlLineData(item1,item2),
            "stroke": "#22a49b",
            "stroke-width": 6/mapScale,
            "c-type": 'outline-translate',
        });
        return el
    }
    return null
    
}
function getOutlinePathMiddleControlLineData(item1,item2){
    const mapScale = store.state[storeName].mapScale;
    const line = [item1[item1.length-1],item2[1]];
    const middle = geometric.lineMidpoint(line);
    const angle = geometric.lineAngle(line);
    const p1 = geometric.pointTranslate(middle,angle,10/mapScale);
    const p2 = geometric.pointTranslate(middle,angle,-10/mapScale);
    return {
        "x1": p1[0],
        "y1": p1[1],
        "x2": p2[0],
        "y2": p2[1],
    }
}

function createOutlinePathItem(item1,item2){
    const mapScale = store.state[storeName].mapScale;
    const styles = {
        "fill": "none",
        "stroke": "#77a3fd",
        "stroke-width": 4/mapScale,
        "line-type": item2[0] == 'C'?'curve':'line',       
        "c-type": 'outline-item',
    }
    return tools.createSvgElement('path',{
        ...styles,
        "d": getPathDFromLinkData(item1,item2)
    })
}

function getPathDFromLinkData(item1,item2){
    const p0 = item1[item1.length-1];
    const p1 = item2[1];
    if(item2[0] == 'L' || item2[0] == 'M'){
        return `M ${p0[0]} ${p0[1]} L ${p1[0]} ${p1[1]}`
    }else if(item2[0] == 'C'){
        return `M ${p0[0]} ${p0[1]} ${tools.curveJoin([...item2[1],...item2[2],...item2[3]])}`
    }
}

function getBorderPointCollect(svgElement){
    //对path进行属性解析
    const d = svgElement.getAttribute('d');
    if(!d)return []
    const collect = d.match(/[M|L|C][\s|\-|\d|\.|,]+\d/g);
    let result: any = [];
    collect.forEach(item=>{
        const order = item.match(/[a-zA-Z]/g);
        if(!util.isEmpty(order)){
            const o = order[0];
            const numberStr = item.replace(/[a-zA-Z]/g,'').trim();
            if(['M','L'].includes(o)){
                const point = numberStr.split(' ').map(n=>parseFloat(n));
                result.push([o,point]);
            }else if(o == 'C'){
                const points = numberStr.split(',').map(v=>{
                    return v.trim().split(' ').map(n=>parseFloat(n));
                })
                result.push([o,...points]);
            }
        }
    })
    return result
}

function resetShape(el,data,updateHelpGrid?:boolean = true){
    let d = getDfromShapeData(data);
    tools.setElementAttribute(el,{d});
    if(updateHelpGrid){
        updateSplitPath();
        updateTransformMark();
    }
    //判断是否是镂空依赖
    if(el.hasAttribute('is-hole')){
        //更新mask的对象项
        const holeInMaskEl = getSvgElementById(shapeContainerIdName).querySelector('#hole-'+el.id);
        tools.setElementAttribute(holeInMaskEl,{d});
    }
    markLayerRender();
    handleSetDeviceSpirit();
}

function getDfromShapeData(data){
    let d = '';
    data.forEach(item=>{
        if(['M','L'].includes(item[0])){
            d += `${item[0]} ${item[1][0]} ${item[1][1]} `
        }else if(item[0]=='C'){
            d += tools.curveJoin([...item[1],...item[2],...item[3]]) + ' ';
        }
        
    })
    d = d + 'Z'
    return d
}

function bindDrawEvent(){
    const container:any = designCanvas.value;
    container.addEventListener('click',designCanvasMouseclick);
    container.addEventListener('mousedown',designCanvasMousedown);
    container.addEventListener('mousemove',designCanvasMousemove);
    container.addEventListener('mouseup',designCanvasMouseup);
    container.addEventListener('contextmenu',designCanvascContextmenu);
    container.addEventListener('mouseover',designCanvasMousehover);
    container.addEventListener('mouseout',designCanvasMousehover);
    document.addEventListener('keydown',documentKeydownEvent);
    document.addEventListener('keyup',documentKeyupEvent);
}

function documentKeydownEvent(e){
    if(leftSelected.value != 'map-move'){
        if(e.keyCode == 32){
            draggableLayout.disabled = false;
            svgDocument.style.pointerEvents = 'none';
            document.body.style.cursor = 'move';
            isSpaceKeyMove = true;
            e.preventDefault();
        }
    }
}

function documentKeyupEvent(e){
    if(leftSelected.value != 'map-move'){
        draggableLayout.disabled = true;
        document.body.style.cursor = 'default';
        svgDocument.style.pointerEvents = 'auto';
        isSpaceKeyMove = false;
        e.preventDefault();
    }
}


function designCanvasMouseclick(e){
    if(isSpaceKeyMove)return
    //console.log('鼠标点击')
    if(isDrawPolygon.value){
        //绘制多边形
        handleDrawPolygon(e);
    }else if(isPointer.value){
        if(isShapeClip){    
            //绘制分割线
            handleShapeClipLine(e);
        }else{
            handleSvgDocumentClick(e);
        }
        
    }else if(isNavigationRoute.value){
        //绘制路径
        handleCreateNavigationLine(e);
    }
}

function designCanvasMousedown(e){
    if(isSpaceKeyMove)return
    isMousedown = true;
    mouseDownPosition = [ e.clientX, e.clientY ];
    mouseDownTarget = e.target;
    //console.log('鼠标按下')
    if(isPointer.value){
        handleShapeTranslateMouseDown(e);
    }
    if(isDrawGeometry.value){
        //绘制标准几何体
       // handleDrawGeometry(e);
    }
    
}

function designCanvasMousemove(e){
    if(isSpaceKeyMove)return
    mouseMovePosition = [ e.clientX, e.clientY ];
    handleUpdateMosetips(e);
    if(isDrawPolygon.value){
        handleDrawPolygonMoving(e);
    }
    if(isDrawGeometry.value&&isMousedown){
        handleDrawGeometry(e);
    }
    if(isPointer.value){
       if(isMousedown)handleShapeTranslateMousemove(e);
       if(isShapeClip)handleShapeClipLine(e);
    }
    if(isRectSelect.value && isMousedown){
        //console.log('框选确定')
        handleDrawRectSelect(e);
    }
    if(isDrawDevice.value && isMousedown){
       // handleDrawDeviceArea();
    }
    
}

function designCanvasMouseup(e){
    document.body.style.cursor = 'default';
    if(isSpaceKeyMove)return
   // mouseDownTarget = null;
    //console.log('鼠标弹起')
    isMousedown = false;
    if(isDrawGeometry.value && getDrawContainer()){
        addDrawShape();
        clearDrawData();
    }
    if(isPointer.value){
        //点拖拽
        handleShapeTranslateMouseup(e);
    }
    if(isRectSelect.value){
        handleDrawRectSelectedResult();
    }
}

function designCanvascContextmenu(e){
    //console.log(e.target,'designCanvascContextmenu----')
    if(isSpaceKeyMove)return
    e.preventDefault();
    if(isDrawPolygon.value){
        if(currentDrawPolygonData.length > 1){
            isDrawing = false;
            handleDrawPolygon(e,'end');
            // currentDrawPolygonData.push(currentDrawPolygonData[0]);
            addDrawShape();
            clearDrawData();
        }
        
    }else if(isPointer.value){
        handleSvgDocumentContextmenu(e);
    }
}

function designCanvasMousehover(e){
    if(isSpaceKeyMove)return
    const type = e.type;
    const cType = e.target.getAttribute('c-type');
    if(!isRectSelect.value){
        if(type == 'mouseover'){
            mouseInMap.value = true;
            if(isShapeElement(e.target)){
                tools.setElementAttribute(e.target,{"stroke": isAddHole?'#68fdf2':"#77a3fd", "stroke-width": 2}) 
            }
            if(cType == 'point-line' || cType == 'nav-point' || cType == 'nav-line'){
                tools.setElementAttribute(e.target,{"stroke": "red"}) 
            }
            if(cType == 'outline-item'){
                tools.setElementAttribute(e.target,{"stroke": "#05286d"}) 
            }
        }
        if(type == 'mouseout'){
            mouseInMap.value = false;
            if(isShapeElement(e.target)){
                tools.setElementAttribute(e.target,{"stroke": polygonStyles["stroke"], "stroke-width": polygonStyles["stroke-width"]})
            }
            if(cType == 'point-line'){
                tools.setElementAttribute(e.target,{"stroke": "#303133"})
            }
            if(cType == 'outline-item'){
                tools.setElementAttribute(e.target,{"stroke": "#77a3fd"}) 
            }
            if(cType == 'nav-point' || cType == 'nav-line'){
                tools.setElementAttribute(e.target,{"stroke": "#67C23A"}) 
            }
        }
    }
}

function addDrawShape(){
    const shape = getDrawContainer().querySelector('path').cloneNode(true);
    const shapeType = isDrawPolygon.value?'polygon':geometryType;
    tools.setElementAttribute(shape,{ 'shape-type': shapeType, id: 'shape_'+uuidv4(), ...polygonStyles });
    // shape.addEventListener('mouseover',(e=>{ 
    //     let strokeColor = '#77a3fd';
    //     if(isAddHole){
    //         strokeColor = '#68fdf2';
    //     }
    //     tools.setElementAttribute(shape,{"stroke": strokeColor, "stroke-width": 2}) 
    // }))
    //shape.addEventListener('mouseout',(e=>{ tools.setElementAttribute(shape,{"stroke": polygonStyles["stroke"], "stroke-width": polygonStyles["stroke-width"]}) }))
    getSvgElementById(shapeContainerIdName).appendChild(shape);
    hanldleHistoryStorage();
    
}

watch(leftSelected,clearDrawData);

function clearDrawData(){
    if(getDrawContainer())getDrawContainer().remove();
    currentDrawPolygonData = [];
}

//绘制导航线
let preNavPoint;
function getNavId(){
    const points = new Set(getSvgElementById(routeContainerIdName).querySelectorAll('circle'));
    const maxId = Math.max(...Array.from(points).map(el=>parseInt(el.id.split('_')[1])));
    return maxId == -Infinity?1:maxId+1
    //
}

function getNavLineByNavPoint(start,end){
    return [
        [ parseFloat(start.getAttribute('cx')), parseFloat(start.getAttribute('cy')) ],
        [ parseFloat(end.getAttribute('cx')), parseFloat(end.getAttribute('cy')) ]
    ]
}

function addNavLine(startPoint:SVGCircleElement,endPoint:SVGCircleElement){
    const lineGroup = getSvgElementById(routeContainerIdName).querySelector('#nav-lines');
    const lines = getNavLineByNavPoint(startPoint, endPoint);
    const properties = {
        "x1": lines[0][0],
        "y1": lines[0][1],
        "x2": lines[1][0],
        "y2": lines[1][1],
        "stroke": "#67C23A",
        "stroke-width": 2,
        "start-id": startPoint.id,
        "end-id": endPoint.id,
        'c-type': 'nav-line'
    }
    const svgLine = tools.createSvgElement('line',properties);
    lineGroup.append(svgLine);
}

function getNavLinesByPoint(pointId){
    const lines = getSvgElementById(routeContainerIdName).querySelector('#nav-lines');
    const lines1 = new Set(lines.querySelectorAll(`[start-id=${pointId}]`));
    const lines2 = new Set(lines.querySelectorAll(`[end-id=${pointId}]`));
    return {
        asStartLines: Array.from(lines1),
        asEndLines: Array.from(lines2)
    }
}

function updateNavLine(line:SVGLineElement|any,startPoint?:SVGCircleElement|null,endPoint?:SVGCircleElement|null){
    const properties = {};
    if(startPoint){
        properties["x1"] = startPoint.getAttribute("cx");
        properties["y1"] = startPoint.getAttribute("cy");
    }
    if(endPoint){
        properties["x2"] = endPoint.getAttribute("cx");
        properties["y2"] = endPoint.getAttribute("cy");
    }
    tools.setElementAttribute(line,properties);
}

function handleCreateNavigationLine(e){
    const transformPoint = transformCoordinate(e.clientX, e.clientY);
    const navContainer = getSvgElementById(routeContainerIdName);
    let lineGroup = getSvgElementById(routeContainerIdName).querySelector('#nav-lines');
    if(!lineGroup){
        lineGroup = tools.createSvgElement('g',{ id: 'nav-lines' });
        getSvgElementById(routeContainerIdName).appendChild(lineGroup);
    }
    const cType = e.target.getAttribute('c-type');
    const circle = tools.createControlCircle(transformPoint,4);
    tools.setElementAttribute(circle,{ id: 'nav_'+getNavId(), 'c-type': 'nav-point' });
    if(cType == 'nav-line'){
        //拆解当前线路
        const startPoint = navContainer.querySelector('#'+e.target.getAttribute('start-id'));
        const middlePoint = circle;
        const endPoint = navContainer.querySelector('#'+e.target.getAttribute('end-id'));
        addNavLine(startPoint,middlePoint);
        addNavLine(middlePoint,endPoint); 
        getSvgElementById(routeContainerIdName).append(middlePoint);
        e.target.remove();
        preNavPoint = circle;
        hanldleHistoryStorage();
        return
    }
    const points = getSvgElementById(routeContainerIdName).querySelectorAll('circle');
    
    if(e.target.getAttribute('c-type')=='nav-point'){
        if(preNavPoint.id == e.target.id){
            return 
        }
        if(!e.shiftKey){
            addNavLine(preNavPoint,e.target); 
            hanldleHistoryStorage();
        }
        preNavPoint = e.target;
        return 
    }
    if(points.length>0){
        if(!preNavPoint)preNavPoint = getSvgElementById(routeContainerIdName).querySelector('circle:last-of-type');
        addNavLine(preNavPoint,circle);
    }
    getSvgElementById(routeContainerIdName).append(circle);
    preNavPoint = circle;
    hanldleHistoryStorage();
}

//分割线绘制
function handleShapeClipLine(e){
    const clipLine = getSvgElementById(clipIdName);
    const p = transformCoordinate(e.clientX,e.clientY);
    if(!clipLine&&e.type == 'click'){
        let properties = {
            "id": clipIdName,
            "x1": p[0],
            "y1": p[1],
            "x2": p[0],
            "y2": p[1],
            "stroke": "red",
            "stroke-width": 2
        }
        svgDocument.appendChild(tools.createSvgElement('line',properties));
    }else{
        tools.setElementAttribute(clipLine,{
            "x2": p[0],
            "y2": p[1],
        })
        if(e.type == 'click'){
            //绘制结束
            drawTips.value = '';
            isShapeClip = false;
            hanleClipResult();
        }
    }
}

function changeCurveShapeToPolygon(paths){
    const newShapeData: any = [];
    paths.forEach((item,index)=>{
        if(item[0] == 'C'){
            const p0 = paths[index-1][paths[index-1].length-1];
            const amount = Math.floor(geometric.lineLength([p0,item[3]])/20)
            const splitResult = splitCurveToLines([p0,item[1],item[2],item[3]],amount);
           // console.log(splitResult,'splitResult------')
            for(let coord of splitResult){
                newShapeData.push(['L',coord])
            }
        }else{
            newShapeData.push(item)
        }
    })
    return newShapeData
}

function hanleClipResult(){
    //计算分割结果
    //分割后的曲线会变为路径点
    const clipEl = getSvgElementById(clipIdName);
    const clipLine = tools.getSvgLineData(clipEl);
    const paths = selectedShapeData;
    const newShapeData = changeCurveShapeToPolygon(paths);//[];
    // paths.forEach((item,index)=>{
    //     if(item[0] == 'C'){
    //         const p0 = paths[index-1][paths[index-1].length-1];
    //         const amount = Math.floor(geometric.lineLength([p0,item[3]])/20)
    //         const splitResult = splitCurveToLines([p0,item[1],item[2],item[3]],amount);
    //        // console.log(splitResult,'splitResult------')
    //         for(let coord of splitResult){
    //             newShapeData.push(['L',coord])
    //         }
    //     }else{
    //         newShapeData.push(item)
    //     }
    // })
    //如果最后一个点和初始点不同则增加一个连接点
    const startPoint = newShapeData[0];
    const endPoint = newShapeData[newShapeData.length-1];
    if(endPoint[1][0] != startPoint[1][0] || endPoint[1][1] != startPoint[1][1])newShapeData.push(['L',startPoint[1]]);
    //console.log(newShapeData,'80898')
    //resetShape(selectedShapeEl,newShapeData);
    //分割逻辑-找到交点-将所有点按照左右排序
    const intersectPointsArray: Array<any> = [];
    newShapeData.map((p,index)=>{
        if(index>0){
            const line = [newShapeData[index-1][1], p[1]];
            const a = { x: clipLine[0][0], y: clipLine[0][1] }
            const b = { x: clipLine[1][0], y: clipLine[1][1] }
            const c = { x: line[0][0], y: line[0][1] }
            const d = { x: line[1][0], y: line[1][1] }
            const intersectPoint = tools.segmentsIntr(a,b,c,d);
            if(intersectPoint){
                intersectPointsArray.push({
                    preIndex: index - 1,
                    nextIndex: index,
                    coord: Object.values(intersectPoint)
                })
            }
        }
    })
    if(intersectPointsArray.length != 2){
        ElMessage({
          message: '分割失败，只能与轮廓有两个确定的交点',
          type: 'error'
        });
        clearSelectStatus();
        clipEl.remove();
        return 
    }
    //分组
    const leftPolygon: any = [];
    const rightPolygon: any = [];
    //let clipPointIsAdd: [boolean, boolean] = [false,false];
    //let rightIsAdd: boolean = false;
    newShapeData.forEach((item,index)=>{
       // const linkPointIndex = intersectPointsArray.findIndex(v=>v.nextIndex == index || v.preIndex == index);

        const currentPointIsPreOfLinkPoint = intersectPointsArray.find(v=>v.preIndex == index);
        const currentPointIsNextOfLinkPoint = intersectPointsArray.find(v=>v.nextIndex == index);

        const isLeft = geometric.pointLeftofLine(item[1], clipLine) || geometric.pointOnLine(item[1], clipLine);
        const polygonSide: any = isLeft?leftPolygon:rightPolygon;
        if(currentPointIsPreOfLinkPoint && currentPointIsNextOfLinkPoint){
            polygonSide.push(['L',currentPointIsNextOfLinkPoint.coord]);
            polygonSide.push(item);
            polygonSide.push(['L',currentPointIsPreOfLinkPoint.coord]);
        }else if(currentPointIsPreOfLinkPoint && !currentPointIsNextOfLinkPoint){
            polygonSide.push(item);
            polygonSide.push(['L',currentPointIsPreOfLinkPoint.coord]);
        }else if(currentPointIsNextOfLinkPoint && !currentPointIsPreOfLinkPoint){
            polygonSide.push(['L',currentPointIsNextOfLinkPoint.coord]);
            polygonSide.push(item);
        }else{
            polygonSide.push(item);
        }
        //const isAddIndex = isLeft?0:1;
        // polygonSide.push(item);
        // if(linkPointIndex>-1 && !clipPointIsAdd[isAddIndex]){
        //     clipPointIsAdd[isAddIndex] = true;
        //     polygonSide.push(['L',intersectPointsArray[linkPointIndex].coord]);
        //     polygonSide.push(['L',intersectPointsArray[linkPointIndex==0?1:0].coord]);
        // }
        // if(geometric.pointLeftofLine(item[1], clipLine) || geometric.pointOnLine(item[1], clipLine) ){
        //     //分配到左边多边形
        //     leftPolygon.push(item);
        //     if(linkPointIndex>-1 && !leftIsAdd){
        //         leftIsAdd = true;
        //         leftPolygon.push(['L',intersectPointsArray[linkPointIndex].coord]);
        //         leftPolygon.push(['L',intersectPointsArray[linkPointIndex==0?1:0].coord]);
        //     }
        // }else{
        //     //分配到右边多边形
        //     rightPolygon.push(item);
        //     if(linkPointIndex>-1 && !rightIsAdd){
        //         rightIsAdd = true;
        //         rightPolygon.push(['L',intersectPointsArray[linkPointIndex].coord]);
        //         rightPolygon.push(['L',intersectPointsArray[linkPointIndex==0?1:0].coord]);
        //     }
        // }
    })
    leftPolygon[0][0] = 'M';
    rightPolygon[0][0] = 'M';
   // leftPolygon.pop();
    //rightPolygon.pop();
    console.log(leftPolygon,rightPolygon,'rightPolygon------');

    //渲染结果
    clipEl.remove();
    selectedShapeEl.remove();
    clearSelectStatus();
    [leftPolygon,rightPolygon].map(shapeData=>{
        // const shape = tools.createSvgElement('path',{
        //     'shape-type': 'polygon',
        //     'id': uuidv4(),
        //     'd': getDfromShapeData(shapeData),
        //     ...polygonStyles
        // })
        // getSvgElementById(shapeContainerIdName).appendChild(shape);
        createShapeFromCalculatedData(shapeData);
    })
    ElMessage({
        message: '分割成功',
        type: 'success'
    });
    hanldleHistoryStorage();
}

function createShapeFromCalculatedData(data){
    const shape = tools.createSvgElement('path',{
        'shape-type': selectedShapeEl?.getAttribute('shape-type') || 'polygon',
        'id': 'shape_'+uuidv4(),
        'd': getDfromShapeData(data),
        ...polygonStyles
    })
    getSvgElementById(shapeContainerIdName).appendChild(shape);
}

//分割曲线为路径点
function splitCurveToLines(curve,length){
    const t = 1/length;
    const lines = [];
    for(let i=0;i<length;i++){
        lines.push(tools.threeBezier(t*(i+1),...curve))
    }
    return lines
}

let rectTransformBasicPoint;
let rectAngle;

//操控数据存储
function handleShapeTranslateMouseDown(e){
    const cType = mouseDownTarget.getAttribute('c-type');
    if(['point-line','outline-translate'].includes(cType)){
        if(isRectShape()){
            rectAngle = geometric.lineAngle([selectedShapeData[0][1],selectedShapeData[1][1]]);
            if(cType == 'point-line'){
                const indexs = mouseDownTarget.getAttribute('indexs');
                const indexArray = indexs.split('_').map(v=>parseInt(v));
                if(isRectShape()){
                    const currentIndex = indexArray[0];
                    const diagonalIndex = currentIndex + 2>3?(currentIndex + 2 - 4):(currentIndex + 2);
                    rectTransformBasicPoint = util.objectCopy(selectedShapeData[diagonalIndex][1]);
                }
            }
        }
    }
}

//shape变换
function handleShapeTranslateMousemove(e){
    if(!mouseDownTarget)return 
    const cType = mouseDownTarget.getAttribute('c-type');
    const startPoint = mouseDownPosition;
    const endPoint = [e.clientX,e.clientY];
    //计算角度和位移
    const line = [startPoint,endPoint];
    const distance = geometric.lineLength(line);
    const angle = geometric.lineAngle(line);
    const position = geometric.pointTranslate(startPoint,angle,distance);
    const offset = transformCoordinate(...position);

    if(cType == 'nav-point'){
        console.log('导航线移动')
        tools.setElementAttribute(mouseDownTarget, { cx: offset[0], cy: offset[1] });
        const lines = getNavLinesByPoint(mouseDownTarget.id);
        lines.asStartLines.forEach(item=>updateNavLine(item,mouseDownTarget));
        lines.asEndLines.forEach(item=>updateNavLine(item,null,mouseDownTarget));
    }

    if(cType == 'spirit'){
        console.log('精灵图移动')
        tools.setElementAttribute(mouseDownTarget, { x: offset[0], y: offset[1] });
    }

    //已选中包围盒事件
    if(!selectedShapeData)return
    if(['point-line','point-curve'].includes(cType)){
        mouseDownTargetDragType = 'point-translate';
        tools.setElementAttribute(mouseDownTarget, { cx: offset[0], cy: offset[1] });
        const indexs = mouseDownTarget.getAttribute('indexs');
        const indexArray = indexs.split('_').map(v=>parseInt(v));
        //矩形特殊处理
        selectedShapeData[indexArray[0]][indexArray[1]] = offset;
        if(isRectShape()){
            //offset需逆向旋转--完成矩形计算后在反向转回圆角度
            const offetRotate = geometric.pointRotate(offset, -rectAngle, rectTransformBasicPoint)
            const coords = geometric.polygonRotate(tools.getRectPointsByStartAndEnd(rectTransformBasicPoint,offetRotate),rectAngle, rectTransformBasicPoint);
            //更新数据和其他控制点
            const pointLineControls = Array.from(new Set(getControlContainer().querySelectorAll('circle[c-type=point-line]')));
            
            selectedShapeData.forEach((item,i)=>{
                item[1] = coords[i];
                tools.setElementAttribute( pointLineControls[i],{
                    cx: coords[i][0], 
                    cy: coords[i][1],
                    indexs: i+`_1`
                })
            })
        }
        
        //需调整曲线
        const lines = Array.from(new Set(getControlContainer().querySelectorAll('line')));
        lines.map(l=>{
            const lineCtype = l.getAttribute('c-type');
            if(lineCtype == 'line-curve'){
                const indexLinkArray = l.getAttribute('index-link').split(',');
                const linkIndex = indexLinkArray.indexOf(indexs);
                if(linkIndex>-1){
                    //关联点
                    tools.setElementAttribute(l,linkIndex==0?{x1: offset[0], y1: offset[1]}:{x2: offset[0], y2: offset[1]})
                }
            }
        })
        resetShape(selectedShapeEl,selectedShapeData);
    }else if(cType == 'c-translate'){
        document.body.style.cursor = 'move';
        //这里节省计算性能和提高体验，将其他控制端隐藏，等鼠标抬起后再重新计算
        mouseDownTargetDragType = 'shape-translate';
        showNecessaryControlEl(['c-translate'])
        tools.setElementAttribute(mouseDownTarget,{ cx: offset[0], cy: offset[1] });
        const distance1 = distance/draggableLayout.getTransform().scale;
        updateHoleShape('translate',{ angle, distance: distance1 });
        resetShape(selectedShapeEl,getShapeTranslateResult(angle,distance1),false);
    }else if(cType == 'c-rotate'){
        mouseDownTargetDragType = 'shape-rotate';
        showNecessaryControlEl(['c-translate','c-rotate','line-transform-rotate']);
        const linkLine = getControlContainer().querySelector("#line-transform-rotate");
        const center = [parseFloat(linkLine.getAttribute('x1')),parseFloat(linkLine.getAttribute('y1'))];
        const angle = geometric.lineAngle([center,offset]);
        updateTransformMark({center,angle});
        updateHoleShape('rotate',{ angle, center });
        resetShape(selectedShapeEl,getShapeRotateResult(angle,center),false);
       // console.log(center,offset,angle,"旋转---afd")
    }else if(cType == 'c-scale'){
        //缩放调整
        mouseDownTargetDragType = 'shape-scale';
        showNecessaryControlEl(['c-translate','c-scale','line-transform-scale']);
        const linkLine = getControlContainer().querySelector("#line-transform-scale");
        const center = [parseFloat(linkLine.getAttribute('x1')),parseFloat(linkLine.getAttribute('y1'))];
        const angle = geometric.lineAngle([center,offset]);
        const moveLineLength = geometric.lineLength([center,offset]);
        //const linkLineLength = geometric.lineLength([center,transformCoordinate(...startPoint)]);
        const oldLineLength = geometric.lineLength([center,transformCoordinate(...startPoint)]);
        const newLinkLineLength = Math.abs(Math.cos(tools.angleToRadian(angle-135))*moveLineLength);
        const scaleFactor = newLinkLineLength/oldLineLength;
        //console.log(moveLineLength,angle-135,newLinkLineLength,oldLineLength,'oldLineLength-------')
        updateTransformMark({center,scaleLineLength:newLinkLineLength});
        updateHoleShape('scale',{ scaleFactor, center });
        resetShape(selectedShapeEl,getShapeScaleResult(scaleFactor,center),false);
    }else if(cType == 'outline-translate'){
        mouseDownTargetDragType = 'shape-line-translate';
        showNecessaryControlEl(['c-outline-paths']);
        const shapeData = util.objectCopy(selectedShapeData);
        const indexLinkString = mouseDownTarget.getAttribute('index-link');
        const indexs = indexLinkString.split(',').map(v=>parseInt(v));
        let distance1 = distance/draggableLayout.getTransform().scale;
        const d1 = shapeData[indexs[0]];
        const d2 = shapeData[indexs[1]];
        let lineAngle = angle;//e.shiftKey?getShiftKeyLimitAngle(angle,startPoint,endPoint):angle;
        if(isRectShape()){
            //矩形只允许定向扩展
            let v1 = 1;
            //角度判断
            let a1 = angle - rectAngle;
            if(indexLinkString=='0,1'){
                lineAngle = rectAngle - 90;
                v1 = a1>-180 && a1<0?1:-1;
            }else if(indexLinkString=='1,2'){
                lineAngle = rectAngle;
                v1 = a1>-90 && a1<90?1:-1;
            }else if(indexLinkString=='2,3'){
                lineAngle = rectAngle + 90;
                v1 = a1>0 && a1<180?1:-1;
            }else if(indexLinkString=='3,0'){
                lineAngle = rectAngle+180;
                v1 = (a1>90 && a1<180) || (a1>-180 && a1< -90)?1:-1;
            }
            //距离判断
            distance1 = distance1*v1;
        }
        const line = [d1[d1.length-1],d2[d2.length-1]];
        const newLine = geometric.lineTranslate(line,lineAngle,distance1);
        shapeData[indexs[0]][d1.length-1] = newLine[0];
        shapeData[indexs[1]][d2.length-1] = newLine[1];
        updateSplitPath(shapeData);
        resetShape(selectedShapeEl,shapeData,false);
        //geometric.lineTranslate
        //shiftKey
    }
}

//根据矩形对角线坐标求另外两个顶点的坐标
function getRectPointByDiagonal(p0,p1){
    const x0 = p0[0];
    const y0 = p0[1];
    const x2 = p1[0];
    const y2 = p1[1];
    const x1 = (x0 + x2 + y2 - y0) / 2;
    const y1 = (x0 + y0 + y2 - x2) / 2;
    const x3 = (x0 + x2 - y2 + y0) / 2;
    const y3 = (y0 + y2 - x0 + x2) / 2;
    return [ [ x1,y1 ], [x3,y3] ]
}

function getShiftKeyLimitAngle(angle,startPoint,endPoint){
    if(angle>45 && angle < 135 || angle>-135 && angle < -45 ){
        //y方向
        return startPoint[1]<endPoint[1]?90:-90;
    }else{
        //x方向
        return startPoint[0]<endPoint[0]?0:180;
    }
}

function updateHoleShape(type,params,shape?:any){
    const maskId = (shape || selectedShapeEl).getAttribute("mask-id");
    if(maskId){
        const { mask, holes } = shape?getShapeMaskData(maskId):selectedShapeHolesData
        let newHoleShapeData;
        for (let holeShapeEl of holes.keys()) {
            const holeInMaskEl = mask.querySelector('#hole-'+holeShapeEl.id);
            if(type == 'translate'){
                const { angle, distance } = params;
                newHoleShapeData = getShapeTranslateResult(angle,distance,holes.get(holeShapeEl));
            }else if(type == 'rotate'){
                const { angle, center } = params;
                newHoleShapeData = getShapeRotateResult(angle,center,holes.get(holeShapeEl));
            }else if(type == 'scale'){
                const { scaleFactor, center } = params;
                newHoleShapeData = getShapeScaleResult(scaleFactor,center,holes.get(holeShapeEl));
            }
            const d = getDfromShapeData(newHoleShapeData);
            tools.setElementAttribute([holeShapeEl,holeInMaskEl],{ d });
        }
    }
}

function showNecessaryControlEl(ids){
    getControlContainer().childNodes.forEach(node=>{
        if(ids.indexOf(node.id)==-1){
            tools.setElementAttribute(node,{ display: 'none' });
        }
    })
}

function handleShapeTranslateMouseup(e){
    if( ['shape-translate','shape-rotate','shape-scale','shape-line-translate'].includes(mouseDownTargetDragType) ){
        setTimeout(() => {
            clearControlContainer();
            setShapeControlBounding(selectedShapeEl);
            hanldleHistoryStorage();
        }, 100);
    }
    if(mouseDownTargetDragType == 'point-translate')hanldleHistoryStorage();
   
    mouseDownTargetDragType = '';
}

//svg 数据提取
//"M 588.127 205.474 L 676.782 399.313 C 20 20, 40 20, 50 10 L 307.887 304.647 L 417.579 173.918 L 588.127 205.474".match(/[M|L|C][\s|\d|\.|,]+\d/g)

//svg mask clippath 剪切蒙版

function getSvgElementById(id){
    return svgDocument.getElementById(id);
}

//控制辅助节点
function createControlSvgContainer(elements){
    return createSvgContainer(elements,controlSvgElementIdName);
}

function getControlContainer(){
    return getSvgElementById(controlSvgElementIdName);
}

//绘制辅助节点
function createDrawingSvgContainer(elements){
    return createSvgContainer(elements,drawingSvgElementIdName);
}
function createSvgContainer(elements,idName){
    let g = tools.createSvgElement('g',{ id: idName });
    elements.forEach(child => {
        g.appendChild(child);
    });
    svgDocument.appendChild(g);
    return g
}
function getDrawContainer(){
    return getSvgElementById(drawingSvgElementIdName);
}

//绘制多边形
function handleDrawPolygon(e,type?:string){
    const transformPoint = transformCoordinate(e.clientX, e.clientY);
    if(currentDrawPolygonData.length == 0){
        isDrawing = true;
        let circle = tools.createDrawingSvgElement('circle', transformPoint);
        let path = tools.createDrawingSvgElement('path', transformPoint);
        let g = createDrawingSvgContainer([path,circle]);
        tools.setElementAttribute(path,{fill: 'rgba(245,203,62,0.3)'})        
    }else{
        let g = getDrawContainer();
        let circle = tools.createDrawingSvgElement('circle', transformPoint);
        g.appendChild(circle);
        if(type=='end'){
            let path = g.querySelector("path");
            let d = path.getAttribute("d");
            tools.setElementAttribute(path,{d: d+" Z"});
            //this.setSelectPointDrag();
        }
    }
    currentDrawPolygonData.push(transformPoint);
}

function handleDrawPolygonMoving(e){
    if (currentDrawPolygonData.length > 0 && isDrawing) {
        let g = getDrawContainer();
        let path = g.querySelector('path');
        const transformPoint = transformCoordinate(e.clientX, e.clientY);
        drawSvgPolygon(currentDrawPolygonData,path);
        let d = path.getAttribute("d");
        d += `L ${transformPoint[0]} ${transformPoint[1]} `
        tools.setElementAttribute(path, { "d": d });
    }
}

//清除选框
function clearRectSelect(){
    rectSelectedData = null;
    svgDocument.getElementById(rectSelectIdName)?.remove();
    if(rectSelectedShapeMap.size>0){
        for (let el of rectSelectedShapeMap.keys()) {
            tools.setElementAttribute(el,{stroke: polygonStyles["stroke"]})
        }
    }
    rectSelectedShapeMap.clear();
    //polygonStyles["stroke"]
}

//绘制选择框
function handleDrawRectSelect(e){
    const mapScale = store.state[storeName].mapScale;
    let path = svgDocument.getElementById(rectSelectIdName);
    if(!path){
        path = tools.createSvgElement('path');
        tools.setElementAttribute(path,{"id": rectSelectIdName})
        svgDocument.appendChild(path);
    }
    const startPoint = transformCoordinate(...mouseDownPosition);
    const endPoint = transformCoordinate(...mouseMovePosition);
    // const p0 = { x: startPoint[0], y: startPoint[1] };
    // const p1 = { x: endPoint[0], y: endPoint[1] };
    rectSelectedData = createRectByPointer(startPoint,endPoint,path,{
        "stroke": "#000",
        "stroke-width": 1/mapScale,
        "fill": 'none',
        "class": "rect-select"
    });   
}

//计算选择结果
function handleDrawRectSelectedResult(){
    //clearRectSelect();
    //获取所有图形 --- rectSelectedData
    const paths = getSvgElementById(shapeContainerIdName).querySelectorAll('path');
    if(!rectSelectedData)return
    rectSelectedShapeMap.clear();
    paths.forEach(el=>{
        if(!el.hasAttribute('is-hole') && !el.id.includes('hole-shape')){
            tools.setElementAttribute(el,{stroke: polygonStyles["stroke"]})
            //图形
            const pointCollect = getBorderPointCollect(el);
            const polygon = getShapeOutlineAll(pointCollect);
            if(geometric.polygonInPolygon(polygon,rectSelectedData) || geometric.polygonIntersectsPolygon(rectSelectedData, polygon)){
                console.log('有相交或在内部的几何',el);
                tools.setElementAttribute(el,{stroke: 'red'})
                rectSelectedShapeMap.set(el,{
                    data: pointCollect,
                    minX: Math.min(...polygon.map(item=>item[0])),
                    minY: Math.min(...polygon.map(item=>item[1])),
                    maxX: Math.max(...polygon.map(item=>item[0])),
                    maxY: Math.max(...polygon.map(item=>item[1])),
                });
            }
        }
    })
}

//对齐功能
function handleShapeAlign(type){
    
    console.log(type,"y87y----")
    const rs = rectSelectedShapeMap;
    if(rs.size<2){
        return 
    }
    if(type == 0){
        //X最小值从小到大排序
        const sortResult = [...rs.keys()].sort((a,b)=>rs.get(a).minX-rs.get(b).minX);
        const minX = rs.get(sortResult[0]).minX;
        const angle = 180;
        sortResult.forEach((el,index)=>{
            if(index>0){
                const distance = rs.get(el).minX - minX;
                resetShape(el,getShapeTranslateResult(angle,distance,rs.get(el).data),false);
                updateHoleShape('translate',{ angle, distance }, el);
            }
            
        })
    }else if(type == 1){
        //X最大值从大到小排序
        const sortResult = [...rs.keys()].sort((a,b)=>rs.get(b).maxX-rs.get(a).maxX);
        const maxX = rs.get(sortResult[0]).maxX;
        const angle = 0;
        sortResult.forEach((el,index)=>{
            if(index>0){
                const distance = maxX - rs.get(el).maxX;
                resetShape(el,getShapeTranslateResult(angle,distance,rs.get(el).data),false);
                updateHoleShape('translate',{ angle, distance }, el);
            }
            
        })
    }else if(type == 2){
        //Y最小值从小到大排序
        const sortResult = [...rs.keys()].sort((a,b)=>rs.get(a).minY-rs.get(b).minY);
        const minY = rs.get(sortResult[0]).minY;
        const angle = -90;
        sortResult.forEach((el,index)=>{
            console.log(rs.get(el),'9898---')
            if(index>0){
                const distance = rs.get(el).minY - minY;
                resetShape(el,getShapeTranslateResult(angle,distance,rs.get(el).data),false);
                updateHoleShape('translate',{ angle, distance }, el);
            }
            
        })
    }else if(type == 3){
        //Y最大值从大到小排序
        const sortResult = [...rs.keys()].sort((a,b)=>rs.get(b).maxY-rs.get(a).maxY);
        const maxY = rs.get(sortResult[0]).maxY;
        const angle = 90;
        sortResult.forEach((el,index)=>{
            if(index>0){
                const distance = maxY - rs.get(el).maxY;
                resetShape(el,getShapeTranslateResult(angle,distance,rs.get(el).data),false);
                updateHoleShape('translate',{ angle, distance }, el);
            }
            
        })
    }
    hanldleHistoryStorage();
}

//绘制标准几何体
function handleDrawGeometry(e){
    //console.log(currentDrawPolygonData,'currentDrawPolygonData')
    //const transformPoint = transformCoordinate(e.clientX, e.clientY);
    const startPoint = transformCoordinate(...mouseDownPosition);
    const endPoint = transformCoordinate(...mouseMovePosition);
    const lineLength = geometric.lineLength([startPoint,endPoint]);
    if(lineLength < 10)return
    let g = getDrawContainer();
    let path;
    if(!g){
        path = tools.createSvgElement('path');
        g = createDrawingSvgContainer([path]);
    }else{
        path = g.querySelector('path');
    }

    if(geometryType == 'circle'){
        const [ x, y ] = startPoint.map(v=>(v-lineLength));
        const { scale } = draggableLayout.getTransform();
        const w = lineLength * 2;
        const h = w;
        tools.createCirclePath(x,y,w,h,path);
    }else if(geometryType == 'half-circle'){
        //绘制半圆
        const [ x, y ] = endPoint.map(v=>(v-lineLength));
        const { scale } = draggableLayout.getTransform();
        const w = lineLength * 2;
        const h = w;
        tools.createHalfCirclePath(x,y,w,h,path);
    }else if(geometryType == 'rect'){
        //tools.setElementAttribute(path,{hasHole: true})
        // const p0 = { x: startPoint[0], y: startPoint[1] };
        // const p1 = { x: endPoint[0], y: endPoint[1] };
        createRectByPointer(startPoint,endPoint,path);
    }
}

function createRectByPointer(start,end,path,styles?:any){
    // let x,y,w = Math.abs(p1.x - p0.x),h = Math.abs(p1.y - p0.y);
    //     //四种方向情况
    //     if (p1.x > p0.x && p1.y > p0.y) {
    //         x = p0.x;
    //         y = p0.y;
    //     } else if (p1.x > p0.x && p1.y < p0.y) {
    //         x = p0.x;
    //         y = p1.y;
    //     } else if (p1.x < p0.x && p1.y > p0.y) {
    //         x = p1.x;
    //         y = p0.y;
    //     } else if (p1.x < p0.x && p1.y < p0.y) {
    //         x = p1.x;
    //         y = p1.y;
    //     } else {
    //         //不做处理
    //         return
    //     }
    //     return tools.createRectPath(x,y,w,h,path,styles);
    return tools.createRectPath(start,end,path,styles);
}


function curveJoin(p){
    return `C ${p[0]} ${p[1]}, ${p[2]} ${p[3]}, ${p[4]} ${p[5]}`
}


function drawSvgPolygon(data,path){
    let d = '';
    for (var i = 0; i < data.length; i++) {
        var p = data[i];
        if (i == 0) {
            d += `M ${p[0]} ${p[1]} `
        } else {
            d += `L ${p[0]} ${p[1]} `
        }
    }
    tools.setElementAttribute(path, { "d": d });
    return path
}

//精灵图标放置
function handleContainerDrop(e){
    const url = e.dataTransfer.getData("SpiritUrl");
    const transformPoint = transformCoordinate(e.clientX, e.clientY);
    if(url){
        const spiritIcon = tools.createSvgElement('image',{ 'c-type': 'spirit', href: url, width: 30, height: 30, x: transformPoint[0], y: transformPoint[1], transform: 'translate(-15, -15)'})
        getSvgElementById(spiritContainerIdName).appendChild(spiritIcon);
    }
}

function windowToMap( x, y ){
    const parentNode = draggableLayout.containerParent;
    var bbox = parentNode.getBoundingClientRect();
    return {x:x-bbox.left, y:y-bbox.top}
}

function transformCoordinate(ox:number, oy:number): [number,number] {
    let position = windowToMap(ox,oy);
    const { scale, transformOrginX, transformOrginY, moveX, moveY } = draggableLayout.getTransform();
    let x = position.x, y = position.y;
    let tox = transformOrginX,
        toy = transformOrginY;
    let bx = (x - tox - moveX) / scale + tox;
    let by = (y - toy - moveY) / scale + toy;

    return  [ bx, by ]
}

function handleUpdateMosetips(e){
    const { x, y } = windowToMap(e.clientX,e.clientY);
    mousePostition.value = [ x, y ]
}

function setLayoutScaleWidthCenter(scale){
    const parentNode = draggableLayout.containerParent;
    const scaleWidth = designWidth.value*scale;
    const scaleHeight = designHeight.value*scale;
    draggableLayout.transformInit({
        moveX: (parentNode.offsetWidth - scaleWidth)/2,
        moveY:(parentNode.offsetHeight - scaleHeight)/2,
        scale
    })
}

onMounted(()=>{
    const el = designCanvas.value;
    draggableLayout = new tools.DraggableContainer(el,{
        wheelEvent: (scale,e)=>{
           // console.log('000 鼠标滚轮---')
            //this.jsPlumbInstance.setZoom(scale);
        },
        transformEvent: (scale,x,y) => {
            store.commit(storeName+'/SET_MAP_SCALE',scale);
            emit('transform-change',{scale,x,y});
            if(selectedShapeEl){
                clearControlContainer();
                setShapeControlBounding(selectedShapeEl);
            }
            

        }

    })
    const parentNode = draggableLayout.containerParent;
    const scale = (parentNode.offsetWidth - 120)>designWidth.value?1:((parentNode.offsetWidth-120)/designWidth.value);
    const scaleWidth = designWidth.value*scale;
    const scaleHeight = designHeight.value*scale;
    draggableLayout.transformInit({
        moveX: (parentNode.offsetWidth - scaleWidth)/2,
        moveY:(parentNode.offsetHeight - scaleHeight)/2,
        scale
    })
    initSvgMap();
})



onUnmounted(()=>{
    //store.unregisterModule(storeName);

})



</script>

<style>
.rect-select{
    stroke-dasharray: 1000;
	stroke-dashoffset: 1000;
    animation: run 10s linear infinite;
}
image[c-type=spirit]:hover{
    outline: auto;
    outline-color: red;
}
/* path:hover{
    stroke: #000;
} */
@keyframes run {
    from {
        stroke-dasharray: 6, 3;
    }
    to {
        stroke-dasharray: 12, 3;
    }
}
</style>

<style lang="scss" scoped>
@import '@/style/common.scss';
.design-layout{
    width: 100%;
    height: 100%;
    background-color: #ecf5ff;
    position: relative;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    :deep(.control-icon) {
        width: 24px;
        height: 24px;
    }
    .mouse-tips{
        position: absolute;
        font-size: 12px;
        background-color: rgba(0,0,0,0.5);
        color: white;
        z-index: 99999;
        pointer-events: none;
        padding: 2px 5px;
    }
    .dl-canvas-box{
        width: 100%;
        height: 100%;
        // display: flex;
        // justify-content: center;
        // align-items: center;
        // overflow: hidden;
        .design-canvas{
            background-color: white;
            //background-image: url(../../assets/images/商场02.jpg);
            background-repeat: no-repeat;
            background-size: 100% 100%;
           // border: 1px solid var(--border-color);
            //box-shadow: 0 0 6px rgba(0,0,0,.1);
        }
    }
    .layout-left{
        height: 100%;
        position: absolute;
        top: 0;
        left: 0;
        border-right: 1px solid var(--border-color);
        box-shadow: 0 2px 6px rgba(0,0,0,0.1);
        z-index: 9;
    }
    .layout-right{
        height: 200px;
        position: absolute;
        top: 0;
        right: 0;
        border-left: 1px solid var(--border-color);
        border-bottom: 1px solid var(--border-color);
        box-shadow: 0 -2px 6px rgba(0,0,0,0.1);
        z-index: 9;
    }
}

</style>